//
//  UniappViewConntroller.swift
//  Runner
//
//  Created by YMac on 2021/1/26.
//  Copyright © 2021 The Chromium Authors. All rights reserved.
//

class YUniappModel: YModel {
    @objc var version = ""
    @objc var url = ""

    required init() { super.init() }
    required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }

    required init(_ version:String, _ url:String) {
        super.init()
        self.version = version
        self.url = url
    }
}

class YUniappPlugin:NSObject, DCUniMPSDKEngineDelegate, URLSessionDelegate {
    var viewController: YUIViewController!
    var appid = ""
    var checkVersionJkid:String?
    var page: String?
    var arguments: [String:Any]?
    var callback: ((_ event: String, _ data: Any?, _ callback: @escaping DCUniMPKeepAliveCallback) -> ())?
    static var isNavigationBarHidden = true

    init(_ viewController: YUIViewController, _ page: String? = nil, _ appid: String = "__UNI__AAAAAAA", _ checkVersionJkid: String? = nil, _ arguments: [String:Any]? =  nil, _ callback: ((_ event: String, _ data: Any?, _ callback: @escaping DCUniMPKeepAliveCallback) -> ())? = nil) {
        self.viewController = viewController
        self.appid = appid
        self.checkVersionJkid = checkVersionJkid
        self.page = page
        self.arguments = arguments
        self.callback = callback
    }

    class func yInit(_ launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) {
        DCUniMPSDKEngine.initSDKEnvironment(launchOptions: launchOptions ?? [UIApplication.LaunchOptionsKey: Any]())
    }

    class func sendEvent(event: String, data: String) {
        DCUniMPSDKEngine.sendUniMPEvent(event, data: data)
    }

    class func finish() {
        (UIApplication.shared.delegate!.window!!.rootViewController as? UINavigationController)?.setNavigationBarHidden(isNavigationBarHidden, animated: true)
        DCUniMPSDKEngine.closeUniMP()
    }

    func run(uniappModel: YUniappModel? = nil) {
        YUniappPlugin.isNavigationBarHidden = (UIApplication.shared.delegate!.window!!.rootViewController as! UINavigationController).isNavigationBarHidden
        if uniappModel == nil && checkVersionJkid == nil {
            viewController.yToast("无法确定小程序版本信息")
            return
        }
        if uniappModel != nil {
            runModel(uniappModel: uniappModel!)
            return
        }
        viewController.yPost(checkVersionJkid!,
                       YJsonKV()
                        .put("appid", appid)
        ) { (isSuccess, yUniappModels:[YUniappModel], _) in
            if isSuccess {
                self.runModel(uniappModel: yUniappModels.first!)
            } else {
                self.loadFail(message: "初始化数据失败", uniappModel: uniappModel)
            }
        }
    }

    private func runModel(uniappModel: YUniappModel){
        if YConfig.DEBUG {
            self.getNewVersion(uniappModel: uniappModel)
        } else {
            if DCUniMPSDKEngine.isExistsApp(self.appid) {
                if Int("\(DCUniMPSDKEngine.getUniMPVersionInfo(withAppid: self.appid)?["code"] ?? 0)")! >= Int(uniappModel.version)! {
                    self.openUniapp(uniappModel: uniappModel)
                } else {
                    self.getNewVersion(uniappModel: uniappModel)
                }
            } else {
                self.getNewVersion(uniappModel: uniappModel)
            }
        }
    }

    private func openUniapp(uniappModel: YUniappModel?) {
        DCUniMPSDKEngine.setMenuButtonHidden(true)
        DCUniMPSDKEngine.setDelegate(self)
        let conf = DCUniMPConfiguration()
        conf.openMode = .push
        conf.arguments = arguments
        conf.redirectPath = page
        viewController.initTheme()
        UIApplication.shared.delegate!.window!!.backgroundColor = UIColor(patternImage: UIImage(named: YConfig.navigationBarBackgroundImage!)!)
        (UIApplication.shared.delegate!.window!!.rootViewController as? UINavigationController)?.setNavigationBarHidden(false, animated: true)
        DCUniMPSDKEngine.openUniMP(appid, configuration: conf) { (uniMPInstance, error) in
            if error != nil { self.loadFail(message: "加载数据失败", uniappModel: uniappModel) }
        }
    }

    private func getNewVersion(uniappModel: YUniappModel) {
        viewController.yShowLoadingProgress()
        URLSession(configuration: .default, delegate: self, delegateQueue: .main).downloadTask(with: URL(string: uniappModel.url + "?v=\(Date().timeIntervalSince1970)")!) { (url, response, error) in
            if error == nil {
                let dir = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!)/Uniapp/"
                try? FileManager().removeItem(at: URL(fileURLWithPath: dir))
                try? FileManager().createDirectory(atPath: dir, withIntermediateDirectories: true, attributes: nil)
                let targetUrl = "\(dir)\(self.appid)_\(uniappModel.version).wgt"
                try? FileManager().copyItem(at: url!, to: URL(fileURLWithPath: targetUrl))
                if DCUniMPSDKEngine.releaseAppResourceToRunPath(withAppid: self.appid, resourceFilePath: targetUrl) {
                    self.viewController.yDismissLoadingProgress()
                    self.openUniapp(uniappModel: uniappModel)
                } else {
                    self.viewController.yDismissLoadingProgress()
                    self.loadFail(message: "加载数据失败", uniappModel: uniappModel)
                }
            } else {
                self.viewController.yDismissLoadingProgress()
                self.loadFail(message: "获取数据失败", uniappModel: uniappModel)
            }
        }.resume()
    }

    private func loadFail(message: String, uniappModel: YUniappModel?) {
        viewController.yShowAlertController(alertView: UIAlertController(title: nil, message: "\(message)，是否重试？", preferredStyle: .alert), hasCancelAction: true, alertActions: [
            UIAlertAction(title: "重试", style: .default, handler: { (_) in
                self.run(uniappModel: uniappModel)
            })
        ])
    }

    func splashView(forApp appid: String) -> UIView {
        let splashView = UIView()
        splashView.backgroundColor = .white
        let progressBar = UIActivityIndicatorView(frame: CGRect(x: viewController.view.frame.width / 2 - 25, y: viewController.view.frame.height / 2 - 25 - 25, width: 50, height: 50))
        progressBar.style = .gray
        progressBar.transform = CGAffineTransform(scaleX: 2, y: 2)
        progressBar.startAnimating()
        splashView.addSubview(progressBar)
        let label = UILabel(frame: CGRect(x: 0, y: viewController.view.frame.height / 2 + 25, width: viewController.view.frame.width, height: 14))
        label.text = "模块加载中，请稍后"
        label.font = UIFont.systemFont(ofSize: 14)
        label.textAlignment = .center
        splashView.addSubview(label)
        return splashView
    }

    func onUniMPEventReceive(_ event: String, data: Any, callback: @escaping DCUniMPKeepAliveCallback) {
        switch event {
        case "yGetDebug":
            callback(YConfig.DEBUG ? "debug" : "release", true)
        case "yGetIP":
            callback(YConfig.IP, true)
        case "yGetAppName":
            callback(YAppUtils.getAppName(), true)
        case "yLog":
            viewController.yPrint("\(data)")
        case "yToast":
            viewController.yToast("\(data)")
        case "yCopy":
            UIPasteboard.general.string = "\(data)"
        case "yOpenBrowser":
            if let url = URL(string: "\(data)") {
                UIApplication.shared.openURL(url)
            }
        default:
            self.callback?(event, data, callback)
        }
    }

    func uniMP(onClose appid: String) {
        (UIApplication.shared.delegate!.window!!.rootViewController as? UINavigationController)?.setNavigationBarHidden(YUniappPlugin.isNavigationBarHidden, animated: true)
    }
    
    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
        }
    }
}
